#include "fontfile.h"
#include "textfile.h"
#include "parser/Parser.h"

#include <sstream>

// "VeraMoBI.ttf_font.txt"
// char id=32    x=486   y=505   width=4     height=4     xoffset=-1.500    yoffset=1.500     xadvance=30.688      page=0  chnl=0
enum T_TokenID
{
	TOKEN_ID=1,
	TOKEN_X,
	TOKEN_Y,
	TOKEN_WIDTH,
	TOKEN_HEIGHT,
	TOKEN_XOFFSET,
	TOKEN_YOFFSET,
	TOKEN_XADVANCE,
	TOKEN_PAGE,
	TOKEN_CHNL
};


void parseFontFile( std::vector<fontChar> &fontChars, std::string &fontfilename, uint texwidth, uint texheight  )
{
	BYTE buffer;
	CParser parser;
	parser.Add((int)TOKEN_ID,		std::string("id="));
	parser.Add((int)TOKEN_X,		std::string("x="));
	parser.Add((int)TOKEN_Y,		std::string("y="));
	parser.Add((int)TOKEN_WIDTH,	std::string("width="));
	parser.Add((int)TOKEN_HEIGHT,	std::string("height="));
	parser.Add((int)TOKEN_XOFFSET,	std::string("xoffset="));
	parser.Add((int)TOKEN_YOFFSET,	std::string("yoffset="));
	parser.Add((int)TOKEN_XADVANCE, std::string("xadvance="));
	parser.Add((int)TOKEN_PAGE,		std::string("page="));
	parser.Add((int)TOKEN_CHNL,		std::string("chnl="));
	parser.Reset();

	uint	id, x, y, width, height;
	float	xoffset, yoffset, xadvance;
	uint	page, chnl;

	// grab the file data, store it and free the new'd block
	char * pFontFile = textFileRead( fontfilename.c_str() );
	std::string allofit(pFontFile);
	delete(pFontFile);

	// process the data
	std::string::const_iterator it=allofit.begin();
	while ( it!=allofit.end() )
	{
		buffer = (*it);
		T_TokenID currentToken = (T_TokenID)parser.CheckForToken(buffer);
		if (NO_TOKEN!=currentToken && buffer=='=')
		{
			++it; // there should never be an '=' before the end of the file ;)
			buffer = (*it);
		}

		switch ( currentToken )
		{
		case NO_TOKEN:
			break; // do nothing but continue searching for a token

		case TOKEN_ID:
			{
				// place your code to handle a token TOKEN_XXX here
				std::string objectStr;
				while (it!=allofit.end() && buffer != ' ')
				{
					objectStr += buffer;
					++it;   if(it!=allofit.end())   buffer = (*it);
				}
				id = atoi( objectStr.c_str() );
			}
			break;

		case TOKEN_X:
			{
				// place your code to handle a token TOKEN_XXX here
				std::string objectStr;
				while (it!=allofit.end() && buffer != ' ')
				{
					objectStr += buffer;
					++it;   if(it!=allofit.end())   buffer = (*it);
				}
				x = atoi( objectStr.c_str() );
			}
			break;

		case TOKEN_Y:
			{
				// place your code to handle a token TOKEN_XXX here
				std::string objectStr;
				while (it!=allofit.end() && buffer != ' ')
				{
					objectStr += buffer;
					++it;   if(it!=allofit.end())   buffer = (*it);
				}
				y = atoi( objectStr.c_str() );
			}
			break;

		case TOKEN_WIDTH:
			{
				// place your code to handle a token TOKEN_XXX here
				std::string objectStr;
				while (it!=allofit.end() && buffer != ' ')
				{
					objectStr += buffer;
					++it;   if(it!=allofit.end())   buffer = (*it);
				}
				width = atoi( objectStr.c_str() );
			}
			break;

		case TOKEN_HEIGHT:
			{
				// place your code to handle a token TOKEN_XXX here
				std::string objectStr;
				while (it!=allofit.end() && buffer != ' ')
				{
					objectStr += buffer;
					++it;   if(it!=allofit.end())   buffer = (*it);
				}
				height = atoi( objectStr.c_str() );
			}
			break;

		case TOKEN_XOFFSET:
			{
				// place your code to handle a token TOKEN_XXX here
				std::string objectStr;
				while (it!=allofit.end() && buffer != ' ')
				{
					objectStr += buffer;
					++it;   if(it!=allofit.end())   buffer = (*it);
				}
				xoffset = static_cast<float>(atof( objectStr.c_str() ));
			}
			break;

		case TOKEN_YOFFSET:
			{
				// place your code to handle a token TOKEN_XXX here
				std::string objectStr;
				while (it!=allofit.end() && buffer != ' ')
				{
					objectStr += buffer;
					++it;   if(it!=allofit.end())   buffer = (*it);
				}
				yoffset = static_cast<float>(atof( objectStr.c_str() ));
			}
			break;

		case TOKEN_XADVANCE:
			{
				// place your code to handle a token TOKEN_XXX here
				std::string objectStr;
				while (it!=allofit.end() && buffer != ' ')
				{
					objectStr += buffer;
					++it;   if(it!=allofit.end())   buffer = (*it);
				}
				xadvance = static_cast<float>(atof( objectStr.c_str() ));
			}
			break;

		case TOKEN_PAGE:
			{
				// place your code to handle a token TOKEN_XXX here
				std::string objectStr;
				while (it!=allofit.end() && buffer != ' ')
				{
					objectStr += buffer;
					++it;   if(it!=allofit.end())   buffer = (*it);
				}
				page = atoi( objectStr.c_str() );
			}
			break;

		case TOKEN_CHNL:
			{
				// place your code to handle a token TOKEN_XXX here
				std::string objectStr;
				while (it!=allofit.end() && buffer != ' ')
				{
					objectStr += buffer;
					++it;   if(it!=allofit.end())   buffer = (*it);
				}
				chnl = atoi( objectStr.c_str() );

				// whatever we've got we can now add to the fontChars :) ... probably
				fontChars.push_back( fontChar(id,x,y,width,height,xoffset,yoffset,xadvance,page,chnl, texwidth, texheight) );
			}
			break;

		default:
			{
				return;
			}
		} // switch ( CheckForToken(buffer) )

		if (it!=allofit.end())
			++it;
	}
}



